<?php

namespace App\Service\Base;


use App\Service\Log\LogFile;
use App\Service\Option;


class Manage
{

    // 需要用的
    protected $error;
    protected $code;
    protected $option;
    protected $name;

    protected $model;
    protected $bang;

    // 翻页等
    // $page $rows 查询的时候最好重新在获取一遍
    /*protected $rows;
    protected $page;
    protected $isPage;
    protected $id;*/

    // 控制器
    /*protected $module;
    protected $controller;
    protected $action;*/

    // 构造方法
    public function __construct()
    {
        $this->name = basename(str_replace('\\', '/', static::class));
        // 参数
        //$this->siteParam();
        // 初始化
        $this->initialize();
    }

    // 初始化
    protected function initialize() { }

    // 获取错误信息
    public function getError()
    {
        return $this->error;
    }

    // 获取错误信息
    public function getCode()
    {
        return $this->code;
    }

    #######################################################################################################
    ## 其他操作

    // 站点常用参数
    protected function siteParam()
    {
        /**
         * 实体 => 符号
         * htmlspecialchars 中文不会乱码（获取的时候过滤，取出数据库的时候也要 htmlspecialchars_decode 过滤）
         * htmlentities  必须制定编码，不然中文乱码
         *
         * 反函数
         * html_entity_decode
         * htmlspecialchars_decode
         */

        // 当前文件名
        $option = $this->option();
        $data   = $option->getData();

        // 控制器
        $parameters       = $option->request()->route()->parameters;
        $this->controller = $data['controller'] ?? ($parameters['controller'] ?? '');
        $this->action     = $data['action'] ?? ($parameters['action'] ?? '');
        $this->module     = $data['module'] ?? ($parameters['module'] ?? 'frontend');

        // 控制器和方法可能是自定义的
        $option->request()->offsetUnset('controller');
        $option->request()->offsetUnset('action');

        //$this->is_debug = Env::get('app_debug');
        $this->isPage = empty($option->getData('page')) ? true : false;
        $this->page   = $option->getData('page', 1, 'intval');
        $this->rows   = $option->getData('rows', 10, 'intval');
        $this->id     = $option->getData('id', 0, 'intval');
        if($this->page < 1){
            $this->page = 1;
        }
        if($this->rows < 1 || $this->rows > 1000){
            $this->rows = 15;
        }

        // 如果重新搜索 变为第一页
        /*if($this->request->isPost()){
            $this->page = 1;
        }*/
    }

    // 日志记录
    protected function log($param, $msg)
    {
        $logger = new LogFile();
        $logger->write($param, $msg);
    }

    // 实例化逻辑参数
    protected function option()
    {
        if(empty($this->option)){
            $this->option = (new Option())->setApp(request());
        }

        return $this->option;
    }


    // 获取当前ip
    protected function ip()
    {
        return $this->option()->getIp();
    }

    // 获取当前ID
    protected function id()
    {
        return $this->option()->getData('id', 0, 'intval');
    }

    // 返回错误
    protected function _returnFail($error, $code = 400)
    {
        $this->error = $error;
        $this->code  = $code;

        return false;
    }


    ###############################################################################################
    ## 数据操作

    // 统计
    protected function getCount()
    {
        $model = $this->checkModel($this->model);
        if($model === false){
            return $this->_returnFail($this->error);
        }

        // 模型 和 查询
        $where = $this->listWhere();
        $nums  = $model->where($where)->count();

        return $nums;
    }

    // 列表
    protected function getLists()
    {
        $opt   = $this->option();
        $page  = $opt->getData('page', 1, 'intval');
        $rows  = $opt->getData('rows', 15, 'intval');
        $start = ($page - 1) * $rows;

        // 模型
        $model = $this->checkModel($this->model);
        if($model === false){
            return $this->_returnFail($this->error);
        }

        // 模型 和 查询
        $where = $this->listWhere();
        $bang  = $this->bang;
        $lists = $model->bangField($bang)->getList($where, $rows, "id DESC", $start);

        return $lists;
    }

    // 列表
    protected function getLists_old()
    {
        $opt   = $this->option();
        $page  = $opt->getData('page', 1, 'intval');
        $rows  = $opt->getData('rows', 15, 'intval');
        $start = ($page - 1) * $rows;

        // 模型
        $model = $this->checkModel($this->model);
        if($model === false){
            return $this->_returnFail($this->error);
        }

        // 模型 和 查询
        $where   = $this->listWhere();
        $isCache = $this->listCache;
        if($isCache != false){
            $KCache = $model->cacheKey('lists', $where);
            $lists  = $model->cacheClass()->getCache($KCache);
            // 检查是否已经绑定
            if(!empty($lists)){
                $model->checkBangList($lists, $KCache);
            }
        }
        if(empty($lists)){
            $lists = $model->getList($where, $rows, "id DESC", $start);
            $lists = is_object($lists) ? $lists->toArray() : $lists;
            if($isCache != false){
                $model->addCacheList($lists, $KCache, $lists, 'list');
            }
        }

        return $lists;
    }

    // 删除
    protected function toDelete()
    {
        $id = $this->id();
        if(empty($id)){
            return $this->_returnFail('请指定要删除的记录！');
        }

        $where = $this->delWhere();
        if($where === false){
            return $this->_returnFail($this->error);
        }

        $model  = $this->checkModel($this->model);
        $result = $model->isCache(true)->oneDelete($where);
        if($result === false){
            return $this->_returnFail($model->getError());
        }

        return $result;
    }

    // 软删除
    protected function toSoft()
    {
        $_id = $this->id();
        if(empty($_id)){
            return $this->_returnFail('请指定删除记录');
        }

        $where = $this->delWhere();
        if($where === false){
            return $this->_returnFail($this->error);
        }

        $model  = $this->checkModel($this->model);
        $result = $model->isCache(true)->oneEdit($where, ['status' => -1]);
        if($result === false){
            return $this->_returnFail($model->getError());
        }

        return $result;
    }

    // 详情
    protected function toShow()
    {
        $where = $this->showWhere();
        if($where === false){
            return $this->_returnFail($this->error);
        }

        $model = $this->checkModel($this->model);
        $info  = $model->isCache(true)->oneFind($where);
        if($info === false){
            return $this->_returnFail($model->getError());
        }

        $info = is_object($info) ? $info->toArray() : $info;

        return $info;
    }

    // 改变
    protected function toChange($field = 'status', $in = [0, 1])
    {
        $opt    = $this->option();
        $_value = $opt->getData('value', null, 'intval');
        $_id    = $opt->getData('id', 0, 'intval');
        if(is_null($_value)){
            return $this->_returnFail('状态必须填写！！');
        }
        if(empty($_id)){
            return $this->_returnFail('请指定操作记录！！');
        }
        if(!in_array($_value, $in)){
            return $this->_returnFail('状态必须为0或1！！');
        }

        // 验证
        $controller = $this->option()->getData('controller');
        if(($controller == 'admin') && ($_id == 1)){
            return $this->_returnFail('第一个管理员不能被禁用或删除！！');
        }

        $model  = $this->checkModel($this->model);
        $result = $model->oneEdit(['id' => $_id], [$field => $_value]);
        if($result === false){
            return $this->_returnFail($model->getError());
        }

        return $result;
    }

    // ajax改变某个字段的值
    protected function changeField($_field, $_value)
    {
        $_id = $this->id();
        if(empty($_id) || empty($_field) || ($_value === '')){
            return $this->_returnFail('请指定修改参数！！');
        }

        // 执行
        $deal   = $this->checkModel($this->model);
        $result = $deal->oneEdit(['id' => $_id], [$_field => $_value]);
        if($result === false){
            return $this->_returnFail($deal->getError());
        }

        return $this->success([], '更新成功！');
    }

    ###############################################################################################
    ## 查询统计
    public function onCount()
    {
        $rows = $this->option()->getData('rows', 15, 'intval');
        $nums = $this->getCount();
        if($nums === false){
            return $this->_returnFail($this->error);
        }

        $pages  = ceil($nums / $rows);
        $result = ['total' => $nums, 'pages' => $pages,];

        return $result;
    }

    // 返回列表数据
    public function onLists()
    {
        $lists = $this->getLists();

        return $lists;
    }

    // 返回每一页的数据（后台使用，返回列表+统计，不在乎快慢）
    public function onPageLists()
    {
        $opt   = $this->option();
        $rows  = $opt->getData('rows', 15, 'intval');
        $page  = $opt->getData('page', 1, 'intval');
        $lists = $this->getLists();
        $nums  = $this->getCount();
        if($nums === false){
            return $this->_returnFail($this->error);
        }

        $result = ['rows' => $rows, 'page' => $page, 'total' => $nums, 'lists' => $lists];

        return $result;
    }


    // 删除
    public function onDelete()
    {
        $result = $this->toDelete();

        return $result;
    }

    // 软删除
    public function onSoft()
    {
        $result = $this->toSoft();

        return $result;
    }

    // 查找
    public function onShow()
    {
        $info = $this->toShow();

        return $info;
    }

    // 启用禁用
    public function onStatus()
    {
        $result = $this->toChange('status', [0, 1]);

        return $result;
    }

    // 改变（直接修改，软删除，改变状态，排序）
    public function onEdit()
    {
        $_id = $this->id();
        if(empty($_id)){
            return $this->_returnFail('请指定修改的ID编号！');
        }

        $data = $this->_before_edit();
        if($data === false){
            return $this->_returnFail($this->error ?: '请添加需要保存的数据！');
        }

        $data = $this->filterNull($data);
        if(empty($data)){
            return $this->_returnFail('请添加需要保存的数据！');
        }

        // 组合数据
        $where = $this->editWhere();
        $model = $this->checkModel($this->model);
        $data  = $model->checkData($data, $where);
        if($data === false){
            return $this->_returnFail('请添加需要保存的数据！');
        }

        // 验证
        $result = $model->checkRules($data, 'edit');
        if($result === false){
            return $this->_returnFail($model->getError());
        }

        // 保存
        $result = $model->oneEdit($where, $data);
        if($result === false){
            return $this->_returnFail($model->getError());
        }

        return $result;
    }

    // 树状
    public function onAdd()
    {
        $data = $this->_before_add();
        if($data === false){
            return $this->_returnFail($this->error ?: '请添加需要保存的数据！');
        }
        $data = $this->filterNull($data);
        if(empty($data)){
            return $this->_returnFail('请添加需要保存的数据！');
        }

        // 组合数据
        $model = $this->checkModel($this->model);
        $data  = $model->checkData($data);
        if($data === false){
            return $this->_returnFail('请添加需要保存的数据！');
        }

        // 验证
        $result = $model->checkRules($data, 'add');
        if($result === false){
            return $this->_returnFail($model->getError());
        }

        // 保存
        $result = $model->oneAdd($data);
        if($result === false){
            return $this->_returnFail($model->getError());
        }

        return $result;
    }

    #######################################################################################################
    ## 操作条件
    // 列表 条件
    protected function listWhere() { return []; }

    protected function editWhere() { return ['id' => $this->id()]; }

    protected function showWhere() { return ['id' => $this->id()]; }

    protected function delWhere() { return ['id' => $this->id()]; }

    #######################################################################################################
    // 过滤为空的字段
    protected function filterNull($data)
    {
        foreach($data as $key => $val){
            if(is_null($val)){
                unset($data[$key]);
            }
        }

        return $data;
    }

    // 判断操作模型是否存在
    protected function checkModel($model = '')
    {
        if(empty($model)){
            return $this->_returnFail("请指定数据模型！！");
        }
        // 模型 与 查询
        $model = 'App\Models\\'.ucwords($model);
        if(!class_exists($model)){
            $request = request();
            $real_ip = $request->getClientIp();
            $test_ip = env('TEST_IP');

            return $this->_returnFail("模型不存在！！");
        }

        return new $model;
    }

    // 关键字查询
    // $where[] = $this->orWhere('title|describe', 'like', $keyword);
    protected function orWhere($column, $type, $value)
    {
        // 失败 同where
        //$query->orWhere([['title', 'like', "%$keyword%"], ['describe', 'like', "%$keyword%"]]);
        // 成功
        //$query->orWhere('title', 'like', "%$keyword%")->orWhere('describe', 'like', "%$keyword%");

        $where = function($query) use ($column, $type, $value) {
            $columns = explode('|', $column);
            if($type == 'like'){
                $value = '%'.$value.'%';
            }
            foreach($columns as $_column){
                $query = $query->orWhere($_column, $type, $value);
            }
        };

        return [$where];
    }

    // 于构建前置与后置操作方法
    public function __call($method, $parameters)
    {
        $before = '_before_'.$method;
        $after  = '_after_'.$method;

        // 前置操作
        if(method_exists($this, $before)){
            $this->{$before}(...array_values($parameters));
        }

        $result = $this->{$method}(...array_values($parameters));

        // 后置操作
        if(method_exists($this, $after)){
            $this->{$after}(...array_values($parameters));
        }

        return $result;
    }

    #######################################################################################################
    ## 前置操作
    // 添加之前
    protected function _before_add()
    {
        return $this->option()->getData();
    }

    // 修改之前
    protected function _before_edit()
    {
        return $this->option()->getData();
    }

    // 修改之前
    protected function _before_change()
    {
        return true;
    }

    // 删除之前
    protected function _before_del()
    {
        return true;
    }

    // 列表之前
    protected function _before_lists()
    {
        return true;
    }

    // 查询之前
    protected function _before_show()
    {
        return true;
    }

    // 查询之前
    protected function _before_find()
    {
        return true;
    }

}
